package p.ithorns.sample.influxdb;

import com.influxdb.client.*;
import com.influxdb.client.domain.*;
import com.influxdb.client.service.InfluxQLQueryService;
import com.influxdb.query.FluxRecord;
import com.influxdb.query.FluxTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.expression.ExpressionParser;
import p.ithorns.sample.influxdb.core.*;
import p.ithorns.sample.influxdb.core.InfluxQLQueryApi;
import p.ithorns.sample.influxdb.mapper.FluxResultBeanMapper;
import p.ithorns.sample.influxdb.mapper.QLResultBeanMapper;

import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;


/**
 * InfluxDB2Example
 *
 * @author HtL
 * @date 2025/1/15 10:36
 * @since 1.0.0
 */
public class InfluxDB2Example {

    private final static Logger log = LoggerFactory.getLogger(InfluxDB2Example.class);

    private static char[] token =
            "Q7EM7CEvZPlpaimJ1umVpAC2mvkRBVRjUPsqqSSLBznjpnu_T-2l5NTdQ__zzNK-0SutUS7y8K4CMYsClvz1Qg=="
                    .toCharArray();
    private static String org = "ithorns";

    private static String orgId = "4c2a5aa59ed97f16";

    private static String bucket = "temp";

    final static InfluxDBClient influxClient =
            InfluxDBClientFactory.create(InfluxDBClientOptions.builder()
                    .url("http://localhost:8086")
                    .authenticateToken(token)
                    .org(org)
                    .bucket(bucket)
                    .precision(WritePrecision.MS)
                    .build());

    public static void main(String[] args) {
        try {
            // createBucketAndGetToken(bucket);
            // write();

//        InfluxDbHelper helper = new InfluxDbHelper(influxClient);
//        helper.readByQL(Home.class, "locate", "select * from home where room = 'Kitchen'");

            //  readQl();

            readByFlux();
            influxClient.close();
        } finally {
            System.exit(0);
        }
    }

    private static void readByFlux() {
        // Query data
        String flux = "from(bucket:\"locate\") "
                + "|> range(start: 0) "
                + "|> filter(fn: (r) => r.room ==\"Kitchen\")"
                + "|> pivot(rowKey:[\"_time\"],columnKey: [\"_field\"],valueColumn: \"_value\")";
        // + "|> filter(fn: (r) => r._field == \"co\")"
        ;

        QueryApi queryApi = influxClient.getQueryApi();
        List<FluxTable> tables = queryApi.query(flux);

        FluxResultBeanMapper mapper = new FluxResultBeanMapper();
        for (FluxTable fluxTable : tables) {
            List<FluxRecord> records = fluxTable.getRecords();
            for (FluxRecord record : records) {
                // System.out.println(toString(record));
                Home pojo = mapper.toBean(record, Home.class);
                System.out.println(pojo);
            }
        }
    }

    private static void readQl() {
        InfluxQLQueryApi api = new InfluxQLQueryApi(influxClient.getService(InfluxQLQueryService.class));
        InfluxQLQuery query = new InfluxQLQuery("select * from home where room = 'Living'", "locate");
        List<QueryRecord> records = api.queryCsv(query, Home.class);

        QLResultBeanMapper mapper = new QLResultBeanMapper();
        for (QueryRecord record : records) {
            Home bean = mapper.toBean(record, Home.class);
            System.out.println(bean);
        }
    }


    private static String toString(FluxRecord record) {
        Map<String, Object> values = record.getValues();
        List<Object> row = record.getRow();
        Integer table = record.getTable();
        String measurement = record.getMeasurement();
        Instant time = record.getTime();
        String field = record.getField();
        Object value = record.getValue();

        Object room = record.getValueByKey("room");
        return table + ":" + room + ":" + time + ":" + field + " -> " + value;
    }

    private static void write() {
        WriteApi writeApi = influxClient.makeWriteApi();
        List<Home> collect = data.lines()
                .map(line -> line.split(" "))
                .map(line -> {
                    // ["home,room="Livi...", "temp=21.1,hum=3...", "1737824000"]
                    // 0 = "home,room="Living""
                    // 1 = "temp=21.1,hum=35.9,co=0i"
                    // 2 = "1737824000"
                    Home home = new Home();
                    home.setRoom(line[0].split(",")[1].split("=")[1]);

                    String[] fields = line[1].split(",");
                    home.setTemp(Double.parseDouble(fields[0].split("=")[1]));
                    home.setHum(Double.parseDouble(fields[1].split("=")[1]));
                    home.setCo(Integer.parseInt(fields[2].split("=")[1].replace("i", "")));
                    home.setTime(Instant.ofEpochSecond(Long.parseLong(line[2])));
                    return home;
                })
                .collect(Collectors.toList());
        System.out.println(collect);
        writeApi.writeMeasurements(WritePrecision.S, collect);
    }

    static String data = """
            home,room=Living temp=21.1,hum=35.9,co=0i 1736984000
            home,room=Kitchen temp=21.0,hum=35.9,co=0i 1736984000
            home,room=Living temp=21.4,hum=35.9,co=0i 1736987600
            home,room=Kitchen temp=23.0,hum=36.2,co=0i 1736987600
            home,room=Living temp=21.8,hum=36.0,co=0i 1736991200
            home,room=Kitchen temp=22.7,hum=36.1,co=0i 1736991200
            home,room=Living temp=22.2,hum=36.0,co=0i 1736994800
            home,room=Kitchen temp=22.4,hum=36.0,co=0i 1736994800
            home,room=Living temp=22.2,hum=35.9,co=0i 1736998400
            home,room=Kitchen temp=22.5,hum=36.0,co=0i 1736998400
            home,room=Living temp=22.4,hum=36.0,co=0i 1737002000
            home,room=Kitchen temp=22.8,hum=36.5,co=1i 1737002000
            home,room=Living temp=22.3,hum=36.1,co=0i 1737005600
            home,room=Kitchen temp=22.8,hum=36.3,co=1i 1737005600
            home,room=Living temp=22.3,hum=36.1,co=1i 1737009200
            home,room=Kitchen temp=22.7,hum=36.2,co=3i 1737009200
            home,room=Living temp=22.4,hum=36.0,co=4i 1737012800
            home,room=Kitchen temp=22.4,hum=36.0,co=7i 1737012800
            home,room=Living temp=22.6,hum=35.9,co=5i 1737016400
            home,room=Kitchen temp=22.7,hum=36.0,co=9i 1737016400
            home,room=Living temp=22.8,hum=36.2,co=9i 1737020000
            home,room=Kitchen temp=23.3,hum=36.9,co=18i 1737020000
            home,room=Living temp=22.5,hum=36.3,co=14i 1737023600
            home,room=Kitchen temp=23.1,hum=36.6,co=22i 1737023600
            home,room=Living temp=22.2,hum=36.4,co=17i 1737027200
            home,room=Kitchen temp=22.7,hum=36.5,co=26i 1737027200
                        """;

}